Skip to main content

FP - 常用的工具與技巧 Map、Filter、Reduce

Map

在 Javascript 中,我們有Array.prototype.map()可以幫助我們將 Array 中 element 依照 callback function 規則一一對應到新的 array,這有助於我們輕鬆的將元素統一『擴展』、『轉換』。

簡單的範例:將 array 每一個元素都乘 5

const multi5 = (x) => x * 5;
let arr = [1, 2, 3, 4, 5];
const result = arr.map(multi5);
console.log(result);
// [5,10,15,20,25]

Filter

Array.prototype.filter()是 Javascript 中原生支援的方法,與Map不同的地方是他會依照 callback function 中的規則篩選條件符合的 element 並且搜集成新的 array

簡單的範例:僅留下陣列中的偶數

const isEven = (x) => x % 2 === 0;
let arr = [1, 2, 3, 4, 5];
const result = arr.filter(isEven);
console.log(result);
// [2,4]

Reduce

Array.prototype.reduce()一樣是 Javascript 中原生支援的方法,這個方法與前兩者有著極大的區別。

reduce 的基礎語法

Array.reduce(
callback[(accumulator, currentValue, currentIndex, array)],
initialValue
);
  • accumulator:經由個別 currentValue 加總的累計值
  • currentValue:Array 的個別 item
  • currentIndex:Array item 的索引
  • array:呼叫該 Array method 的陣列
  • initialValue:預設值,放在 function 的最後方,非必填

其中比較特別的是 accumulatorinitialValue,在其他的陣列方法裡也少見。用文字敘述可能會不太清楚這些參數的意思,這裡用最簡單的陣列數值加總為例,並預設兩種不同狀況:

簡單的範例:

1. 計算最大值

const arr = [1, 2, 3, 4];
const initVal = 0;
const result = arr.reduce(
(accumulator, current) => accumulator + current,
initVal
);
console.log(result);
// 10
loop 第幾次accumulatorcurrent valuereturn value
1123
2336
36410

2. 將陣列中重複的元素去除

const numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
const uniqueNumbers = numbers.reduce((acc, current) => {
if (!acc.includes(current)) {
acc.push(current);
}
return acc;
}, []);
console.log(uniqueNumbers); // [1, 2, 3, 4]

3. 計算每個元素出現的次數

const numbers = [1, 2, 3, 2, 2, 3, 3, 4, 2, 4];
const count = numbers.reduce((acc, current) => {
if (acc[current]) {
acc[current] += 1;
} else {
acc[current] = 1;
}
return acc;
}, {});
console.log(count); // {1: 1, 2: 4, 3: 3, 4: 2}

4. 將二維陣列攤平

const arrays = [[1, 2], [3, 4], [5, 6]];
const flattened = arrays.reduce((acc, current) => acc.concat(current), []);
console.log(flattened); // [1, 2, 3, 4, 5, 6]

5. 根據物件中的某個屬性進行分組

const data = [
{ id: 1, category: 'A' },
{ id: 2, category: 'B' },
{ id: 3, category: 'A' },
{ id: 4, category: 'C' },
{ id: 5, category: 'B' }
];

const groupedData = data.reduce((acc, current) => {
(acc[current.category] = acc[current.category] || []).push(current);
return acc;
}, {});

console.log(groupedData);
// {
// A: [{ id: 1, category: 'A' }, { id: 3, category: 'A' }],
// B: [{ id: 2, category: 'B' }, { id: 5, category: 'B' }],
// C: [{ id: 4, category: 'C' }]
// }